﻿using System;
using System.Collections.Generic;



namespace DailyFx.Book
{

	public class Schema : IEquatable<Schema> // table schema .
	{
		/// <summary>
		///		
		/// </summary>
		private readonly List<Field> _fields = new List<Field>();


		/// <summary>
		///		Gets the table's schema human-readable label text . 
		/// </summary>
		public string Alias
		{
			get;
			set;
		}

		/// <summary> 
		///		Gets the number of <see cref="Field"/>s contained in the <see cref="Schema"/>. 
		/// </summary> 
		public Int32 FieldCount
		{
			get { return this._fields.Count; }
		}

		/// <summary> 
		///		Checks if the <see cref="Schema"/> contains a field with specific label . 
		/// </summary> 
		public bool IfFieldExists ( string fLabel )
		{
			return this._fields.Exists ( x => x.Label == fLabel );
		}

		/// <summary>
		///		Gets the label of the field at specified index .
		/// </summary>
		public string GetFieldLabel ( int index )
		{
			return this._fields[ index ].Label;
		}

		/// <summary> 
		///		Checks if the index of a <see cref="Field"/> in the <see cref="Schema"/> by given label. 
		/// </summary> 
		public Int32 GetFieldIndex ( String fLabel )
		{
			return this._fields.FindIndex( x => x.Label == fLabel );
		}

		/// <summary>
		///		Gets the type info of the field .
		/// </summary>
		public Type GetFieldType ( string fLabel )
		{
			int index = this.GetFieldIndex( fLabel );
			
			if ( index < 0 )
				return null;

			return this.GetFieldType( index );
		}

		/// <summary>
		///		Gets the type info of the field at specified index .
		/// </summary>
		public Type GetFieldType ( int index )
		{
			return this._fields[ index].Type; 
		}


		/// <summary> 
		///		Adds new field definition to the <see cref="Schema"/>. 
		/// </summary> 
		public void AddField ( String fLabel, Type fType )
		{
			this._fields.Add ( new Field( fLabel, fType) );
		}

		/// <summary> 
		///		Inserts an item to the <see cref="Schema"/> at the specified index. 
		/// </summary> 
		public void InsertField (Int32 index, String fLabel, Type fType )
		{
			this._fields.Insert( index, new Field(fLabel, fType) );
		}

		/// <summary> 
		///		Removes the <see cref="Metrics"/> item at the specified index. 
		///		- not supported as collection is read-only. 
		/// </summary> 
		public void DeleteField ( String fLabel )
		{
			int index = this.GetFieldIndex( fLabel);
			if ( index != -1 )
				this._fields.RemoveAt( index);
		}


		/**
		 
		/// <summary> 
		///		Gets the <see cref="Field"/> at the specified index. 
		/// </summary> 
		public Field this [ Int32 index ]
		{
			get
			{
				return this._fields[index];
			}
			set
			{
				throw new NotSupportedException();
			}
		}

		/// <summary> 
		///		Gets the <see cref="Yap.Data.Client.Field"/> by the specified name. 
		/// </summary> 
		public Field this [ String name ]
		{
			get
			{
				Int32 index = this._fields.FindIndex( x => x.Label == fLabel );
				if ( index == -1)
				{
					return null;
				}
				return this [ index ];
			}
		}
		 
		*/

		public bool Equals ( Schema other )
		{
			if ( other == null )
				return false;

			if ( this.Alias == other.Alias )
				return true;

			// It's allowed that 2 schemas has same fields definition . 
			// if ( this._fields.)

			return false;
		}

		//
		public override bool Equals( object obj )
		{
			return this.Equals ( obj as Schema );
		}

		// 
		public override int GetHashCode()
		{
			return this.Alias.GetHashCode();
		}

		//
		public override string ToString()
		{
			return "Schema: " + this.Alias;
		}
	}
}
